﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Resources;
using System.Windows;
using System.Windows.Media.Imaging;
using GlobalizationTools.Model;
using System.Windows.Input;
using System.Windows.Controls;
using GlobalizationTools.UI;


namespace GlobalizationTools.ViewModel
{
    public class TabControlItemViewModel : CommandViewModel
    {
        public static RoutedUICommandEx CloseCommand = new RoutedUICommandEx(LocalizationResource.Close, "Close", typeof(TabControlItemViewModel), "/ViewModel/Images/Close.png", Key.C, ModifierKeys.Control);

        public override void AddCommandModels(List<CommandBinding> List)
        {
            List.Add(new CommandBinding(CloseCommand, ExecuteClose, CanExecuteClose));
        }

        public override void AddInputModels(List<InputBinding> List)
        {
        }

        private static string DefaultValueColumnName = LocalizationResource.Value;
        ObservableCollection<DataGridColumn> _columns = new ObservableCollection<DataGridColumn>();
        int _currentTypeIndex = 0;
        readonly Resource _resource;
        TreeViewResourceViewModel _parent;
        ObservableCollection<Resource> _languages = new ObservableCollection<Resource>();
        string _name;
        readonly string _nameCache;
        //bool _isSelected = false;
        ObservableCollection<ResourceEntry> _List = new ObservableCollection<ResourceEntry>();
        bool _IsModified = false;

        static TabControlItemViewModel()
        {
            /*CommandManager.RegisterClassCommandBinding(typeof(TabControlItemViewModel),
                new CommandBinding(Commands.CloseCommand, 
                new ExecutedRoutedEventHandler(cb_Executed), new CanExecuteRoutedEventHandler(cb_CanExecute)));*/
        }

        public TabControlItemViewModel(TreeViewResourceViewModel parent)
        {
            _parent = parent;
            _resource = _parent.Resource;
            _nameCache = Path.GetFileNameWithoutExtension(_resource.FilePath);
            _name = _nameCache;
            _languages.CollectionChanged += new NotifyCollectionChangedEventHandler(_languages_CollectionChanged);
            LoadAllResources();
        }

        void _languages_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            foreach (Resource resource in e.NewItems)
            {
                LoadResource(resource);
            }
        }

        private void LoadAllResources()
        {
            _List.Clear();
            _columns.Clear();
            IsModified = false;
            LoadResource(_resource);
            foreach (Resource resource in _languages)
            {
                LoadResource(resource);
            }
        }

        private int GetResourcePosition(Resource resource)
        {
            int pos = 0;
            if (resource != _resource)
                pos = _languages.IndexOf(resource) + 1;
            return pos;
        }

        private void LoadResource(Resource resource)
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.Parent.StatusText = LocalizationResource.Loading;

                if (!resource.IsLoaded)
                    resource.LoadResource();
                int pos = GetResourcePosition(resource);
                if (resource.Data.ContainsKey(_currentTypeIndex))
                {
                    foreach (KeyValuePair<string, ResXDataNode> node in resource.Data[_currentTypeIndex])
                    {
                        ResourceEntry entry = GetResourceEntry(node.Key);
                        InsertResourceData(entry, pos, GetValue(node.Value));
                    }
                }
                foreach (ResourceEntry entry in _List)
                {
                    while (entry.Values.Count <= pos)
                    {
                        entry.Values.Add(new ResourceData(this));
                    }
                }
                LoadColumn(pos);
            }
            finally
            {
                this.Parent.StatusText = LocalizationResource.Ready;
                Mouse.OverrideCursor = null;
            }
        }

        private void SaveAllEntries()
        {
            foreach (ResourceEntry entry in _List)
            {
                SaveEntry(entry);
            }
        }

        private void SaveEntry(ResourceEntry entry)
        {
            SaveResourceEntry(entry, _resource, 0);
            int i = 1;
            foreach (Resource resource in _languages)
            {
                SaveResourceEntry(entry, resource, i);
                i++;
            }
            if (entry.Name != entry.OriginalName)
            {
                entry.OriginalName = entry.Name;
            }
        }

        private void SaveResourceEntry(ResourceEntry entry, Resource resource, int pos)
        {
            ResourceData data = entry.Values[pos];
            if (entry.Name != entry.OriginalName || data.IsModified)
            {
                ResXDataNode original = null;
                if (!resource.Data.ContainsKey(_currentTypeIndex))
                {
                    resource.Data.Add(_currentTypeIndex, new Dictionary<string, ResXDataNode>());
                }
                if (resource.Data[_currentTypeIndex].ContainsKey(entry.OriginalName))
                {
                    original = resource.Data[_currentTypeIndex][entry.OriginalName];
                    if (entry.Name != entry.OriginalName)
                    {
                        resource.Data[_currentTypeIndex].Remove(entry.OriginalName);
                    }
                }
                ResXDataNode newNode = GetNewNode(entry.Name, original, data.Value);
                if (resource.Data[_currentTypeIndex].ContainsKey(entry.Name))
                {
                    resource.Data[_currentTypeIndex][entry.Name] = newNode;
                }
                else
                {
                    resource.Data[_currentTypeIndex].Add(entry.Name, newNode);
                }
                data.IsModified = false;
            }
        }

        private ResXDataNode GetNewNode(string name, ResXDataNode original, object value)
        {
            ResXDataNode result = null;
            if (original != null && original.FileRef != null)
            {
                result = new ResXDataNode(name, original.FileRef);
            }
            else
            {
                result = new ResXDataNode(name, value);
            }
            if (original != null)
            {
                result.Comment = original.Comment;
            }
            return result;
        }

        private void LoadColumn(int pos)
        {
            int i = _columns.Count;
            while (_columns.Count <= pos)
            {
                string name = DefaultValueColumnName;
                Resource resource = _resource;
                if (i > 0)
                    resource = _languages[i - 1];
                if (resource.CultureInfo != null)
                    name = resource.CultureInfo.DisplayName;
                DataGridColumn column = DataGridColumnUtil.GetColumn(
                    ResourceUtils.TypesList[_currentTypeIndex],
                    name, i);
                _columns.Add(column);
                i++;
            }
        }

        private object GetValue(ResXDataNode node)
        {
            if (ResourceUtils.TypesList[_currentTypeIndex] == ResourceUtils.ImageTypeName)
            {
                BitmapImage image = new BitmapImage(new Uri(node.FileRef.FileName));
                return image;
            }
            return node.GetValue(ResourceUtils.TypeResolutionService);
        }

        private void InsertResourceData(ResourceEntry entry, int pos, object value)
        {
            while (entry.Values.Count < pos)
            {
                entry.Values.Add(new ResourceData(this));
            }
            entry.Values.Add(new ResourceData(this, value));
        }

        private ResourceEntry GetResourceEntry(string name)
        {
            ResourceEntry entry = _List.Where(T => T.Name == name).SingleOrDefault();
            if (entry == null)
            {
                entry = new ResourceEntry(name);
                _List.Add(entry);
            }
            return entry;
        }

        public int CurrentTypeIndex
        {
            get
            {
                return _currentTypeIndex;
            }
            set
            {
                if (_currentTypeIndex != value)
                {
                    if (AskToSave())
                    {
                        _currentTypeIndex = value;
                        LoadAllResources();
                        OnPropertyChanged("CurrentTypeIndex");
                    }
                }
            }
        }

        public bool IsModified
        {
            get { return _IsModified; }
            set
            {
                if (_IsModified != value)
                {
                    _IsModified = value;
                    OnPropertyChanged("IsModified");
                    _name = _IsModified ? string.Concat(_nameCache, '*') : _nameCache;
                    OnPropertyChanged("Name");
                }
            }
        }

        public TreeViewResourceViewModel Parent
        {
            get { return _parent; }
        }

        public Resource Resource
        {
            get { return _resource; }
        }

        public string Name
        {
            get
            {
                return _name;
            }
        }

        public ObservableCollection<ResourceEntry> List
        {
            get { return _List; }
        }

        public ObservableCollection<Resource> Languages
        {
            get { return _languages; }
        }

        public ObservableCollection<DataGridColumn> Columns
        {
            get { return _columns; }
        }

        public bool AskToSave()
        {
            bool result = true;
            if (_IsModified)
            {
                MessageBoxResult boxResult = MessageBox.Show(string.Format(LocalizationResource.WantSaveChanged,this.Parent.FileName), LocalizationResource.SaveChanged, MessageBoxButton.YesNoCancel, MessageBoxImage.Question, MessageBoxResult.Cancel);
                switch (boxResult)
                {
                    case MessageBoxResult.Yes:
                        Save();
                        break;
                    case MessageBoxResult.Cancel:
                        result = false;
                        break;
                }
            }
            return result;
        }

        public void Save()
        {
            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                this.Parent.StatusText = LocalizationResource.Loading;

                this.SaveAllEntries();
                _resource.SaveResource();
                foreach (Resource resource in _languages)
                {
                    resource.SaveResource();
                }
                IsModified = false;
            }
            finally
            {
                this.Parent.StatusText = LocalizationResource.Ready;
                Mouse.OverrideCursor = null;
            }
        }

        /*public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }*/






        /*static void cb_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        static void cb_Executed(object sender, ExecutedRoutedEventArgs e)
        {

        }





        public static class Commands
        {
            private static RoutedUICommand _CloseCommand;

            static Commands()
            {
                _CloseCommand = new RoutedUICommand("CloseCommand", "CloseCommand",
                    typeof(TabControlItemViewModel));
            }

            public static ICommand CloseCommand
            {
                get { return _CloseCommand; }
            }
        }*/


        protected void ExecuteClose(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parent.Close();
        }

        protected void CanExecuteClose(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
            e.Handled = true;
        }


    }
}
